From 0e099fb6bdbedcbdd8abb2509b3024febf2dc01d Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Wed, 2 May 2007 09:39:34 +0000 Subject: [PATCH] removed, since this file is long outdated and fully replaced by Wed May 2 11:35:45 2007 Tim Janik * docs/faq/gtkfaq.sgml: removed, since this file is long outdated and fully replaced by docs/faq/gtk-faq.sgml. svn path=/trunk/; revision=17772 --- ChangeLog | 5 + docs/faq/gtkfaq.sgml | 2982 ------------------------------------------ 2 files changed, 5 insertions(+), 2982 deletions(-) delete mode 100644 docs/faq/gtkfaq.sgml diff --git a/ChangeLog b/ChangeLog index 39030488e6..b36c2f0324 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +Wed May 2 11:35:45 2007 Tim Janik + + * docs/faq/gtkfaq.sgml: removed, since this file is long outdated + and fully replaced by docs/faq/gtk-faq.sgml. + 2007-05-02 Kristian Rietveld * gtk/gtktreeview.c (gtk_tree_view_grab_notify): stop the rubber band diff --git a/docs/faq/gtkfaq.sgml b/docs/faq/gtkfaq.sgml deleted file mode 100644 index bc914ae0c0..0000000000 --- a/docs/faq/gtkfaq.sgml +++ /dev/null @@ -1,2982 +0,0 @@ - - -
- - - -GTK+ FAQ - -<!-- NOTE: Use only one author tag, otherwise sgml2txt barfs - TRG --> -<author>Tony Gale, Shawn T. Amundson, Emmanuel Deloget, Nathan Froyd - -<date>March 9th 2000 - -<abstract> This document is intended to answer questions that are likely to be -frequently asked by programmers using GTK+ or people who are just looking at -using GTK+. -</abstract> - -<!-- Table of contents --> -<toc> - -<!-- Begin the document --> - -<!-- ***************************************************************** --> -<sect>General Information - -<!-- ----------------------------------------------------------------- --> -<sect1>Before anything else: the greetings -<p> -The FAQ authors want to thank: -<itemize> -<item>Havoc Pennington -<item>Erik Mouw -<item>Owen Taylor -<item>Tim Janik -<item>Thomas Mailund Jensen -<item>Joe Pfeiffer -<item>Andy Kahn -<item>Federico Mena Quintero -<item>Damon Chaplin -<item>and all the members of the GTK+ lists -</itemize> -If we forgot you, please email us ! -Thanks again (I know, it's really short :) - -<!-- ----------------------------------------------------------------- --> -<sect1>Authors -<p> -The original authors of GTK+ were: - -<itemize> -<item>Peter Mattis -<item>Spencer Kimball -<item>Josh MacDonald -</itemize> - -Since then, much has been added by others. Please see the AUTHORS -file in the distribution for the GTK+ Team. - -<!-- ----------------------------------------------------------------- --> -<sect1>What is GTK+? -<p> -GTK+ is a small and efficient widget set designed with the general -look and feel of Motif. In reality, it looks much better than Motif. -It contains common widgets and some more complex widgets such as a -file selection, and color selection widgets. - -GTK+ provides some unique features. (At least, I know of no other -widget library which provides them). For example, a button does not -contain a label, it contains a child widget, which in most instances -will be a label. However, the child widget can also be a pixmap, -image or any combination possible the programmer desires. This -flexibility is adhered to throughout the library. - -<!-- ----------------------------------------------------------------- --> -<sect1>What is the + in GTK+? -<P> -Peter Mattis informed the gtk mailing list that: -<quote> -"I originally wrote gtk which included the three libraries, libglib, -libgdk and libgtk. It featured a flat widget hierarchy. That is, you -couldn't derive a new widget from an existing one. And it contained -a more standard callback mechanism instead of the signal mechanism now -present in gtk+. The + was added to distinguish between the original -version of gtk and the new version. You can think of it as being an -enhancement to the original gtk that adds object oriented features." -</quote> - -<!-- ----------------------------------------------------------------- --> -<sect1>Does the G in GTK+, GDK and GLib stand for? -<p> -GTK+ == Gimp Toolkit - -GDK == GTK+ Drawing Kit - -GLib == G Libray - -<!-- ----------------------------------------------------------------- --> -<sect1>Where is the documentation for GTK+? -<p> -In the GTK+ distribution's doc/ directory you will find the -reference material for both GTK and GDK, this FAQ and the -GTK Tutorial. - -In addition, you can find links to HTML versions of these documents -by going to <htmlurl url="http://www.gtk.org/" -name="http://www.gtk.org/">. A packaged version of the GTK Tutorial, -with SGML, HTML, Postscript, DVI and text versions can be found in -<htmlurl url="ftp://ftp.gtk.org/pub/gtk/tutorial" -name="ftp://ftp.gtk.org/pub/gtk/tutorial"> - -There are now a couple of books available that deal with programming -GTK+, GDK and GNOME: -<itemize> -<item> Eric Harlows book entitled "Developing Linux Applications with -GTK+ and GDK". The ISBN is 0-7357-0021-4 -<P> -The example code from Eric's book is available on-line at -<htmlurl url="http://www.bcpl.net/~eharlow/book" -name="http://www.bcpl.net/~eharlow/book"> - -<item> Havoc Pennington has released a book called "GTK+/GNOME -Application Development". The ISBN is 0-7357-0078-8 -<P> -The free version of the book lives here: -<htmlurl url="http://developer.gnome.org/doc/GGAD/" -name="http://developer.gnome.org/doc/GGAD/"> -<P> -And Havoc maintains information about it and errata here: -<htmlurl url="http://pobox.com/~hp/gnome-app-devel.html" -name="http://pobox.com/~hp/gnome-app-devel.html"> -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Is there a mailing list (or mailing list archive) for GTK+? -<p> -Information on mailing lists relating to GTK+ can be found at: - -<htmlurl url="http://www.gtk.org/mailinglists.html" -name="http://www.gtk.org/mailinglists.html"> - -<!-- ----------------------------------------------------------------- --> -<sect1>How to get help with GTK+ -<p> -First, make sure your question isn't answered in the documentation, -this FAQ or the tutorial. Done that? You're sure you've done that, -right? In that case, the best place to post questions is to the GTK+ -mailing list. - -<!-- ----------------------------------------------------------------- --> -<sect1>How to report bugs in GTK+ -<p> -Bugs should be reported to the GNOME bug tracking -system (<htmlurl url="http://bugs.gnome.org" -name="http://bugs.gnome.org">). To report a problem about GTK+, send -mail to submit@bugs.gnome.org. - -The subject of the mail should describe your problem. In the body of -the mail, you should first include a "pseudo-header" that gives the -package and version number. This should be separated by a blank line -from the actual headers. - -<verb> - Package: gtk+ - Version: 1.2.0 -</verb> - -Substitute 1.2.0 with the version of GTK+ that you have installed. - -Then describe the bug. Include: - -<itemize> -<item> Information about your system. For instance: - <itemize> - <item> What operating system and version - <item> What version of X - <item> For Linux, what version of the C library - </itemize> - And anything else you think is relevant. - -<item> How to reproduce the bug. - - If you can reproduce it with the testgtk program that is built in - the gtk/ subdirectory, that will be most convenient. Otherwise, - please include a short test program that exhibits the behavior. As - a last resort, you can also provide a pointer to a larger piece of - software that can be downloaded. - - (Bugs that can be reproduced within the GIMP are almost as good as - bugs that can be reproduced in testgtk. If you are reporting a bug - found with the GIMP, please include the version number of the GIMP - you are using) - -<item> If the bug was a crash, the exact text that was printed out - when the crash occured. - -<item> Further information such as stack traces may be useful, but are - not necessary. If you do send a stack trace, and the error is an X - error, it will be more useful if the stacktrace is produced running - the test program with the <tt/--sync/ command line option. -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>Is there a Windows version of GTK+? -<p> -There is an on going port of GTK+ to the Windows platform which is -making impressive progress. - -See <htmlurl url="http://www.iki.fi/tml/gimp/win32" -name="http://www.iki.fi/tml/gimp/win32"> for more information. - -<!-- ----------------------------------------------------------------- --> -<sect1>What applications have been written with GTK+? -<p> -A list of some GTK+ based application can be found on the GTK+ web -server at <htmlurl url="http://www.gtk.org/apps/" -name="http://www.gtk.org/apps/"> and contains more than 350 -applications. - -Failing that, look for a project to work on for the GNOME project, -<htmlurl url="http://www.gnome.org/" name="http://www.gnome.org/"> -Write a game. Write something that is useful. - -Some of these are: -<itemize> -<item>GIMP (<htmlurl url="http://www.gimp.org/" - name="http://www.gimp.org/">), - an image manipulation program -<item>AbiWord (<htmlurl url="http://www.abisource.com/" - name="http://www.abisource.com/">), - a professional word processor -<item>GUBI (<htmlurl url="http://www.SoftHome.net/pub/users/timj/gubi/index.htm" - name="http://www.SoftHome.net/pub/users/timj/gubi/index.htm">), - a user interface builder -<item>Gzilla (<htmlurl url="http://www.levien.com/gzilla/" - name="http://www.levien.com/gzilla/">), - a web browser -<item>SANE (<htmlurl url="http://www.azstarnet.com/~axplinux/sane/" - name="http://www.azstarnet.com/~axplinux/sane/"> ), - a universal scanner interface -<item>XQF (<htmlurl url="http://www.botik.ru/~roma/quake/" - name="http://www.botik.ru/~roma/quake/">), - a QuakeWorld/Quake2 server browser and launcher -<item>ElectricEyes (<htmlurl url="http://www.labs.redhat.com/ee.shtml" - name="http://www.labs.redhat.com/ee.shtml">), - an image viewer that aims to be a free replacement for xv -<item>GPK - the General Proxy Kit (<htmlurl url="http://www.humanfactor.com/gpk/" - name="http://www.humanfactor.com/gpk/">), - an add-on library to permit thread-safe access to GTK+ -<item>GCK - the General Convenience Kit (<htmlurl url="http://www.ii.uib.no/~tomb/gck.html" - name="http://www.ii.uib.no/~tomb/gck.html">), - miscellaneous functions intended to ease color handling, UI construction, - vector operations, and math functions -<item>GDK Imlib (<htmlurl url="http://www.labs.redhat.com/imlib/" - name="http://www.labs.redhat.com/imlib/">), - a fast image loading and manipulation library for GDK -<item>Glade (<htmlurl url="http://glade.pn.org/" - name="http://glade.pn.org/">), - a GTK+ based RAD tool which produces GTK+ applications -</itemize> -<p> -In addition to the above, the GNOME project (<htmlurl -url="http://www.gnome.org" name="http://www.gnome.org">) is using GTK+ -to build a free desktop for Linux. Many more programs can be found -there. - -<!-- ----------------------------------------------------------------- --> -<sect1>I'm looking for an application to write in GTK+. How about an IRC client? -<p> - -Ask on gtk-list for suggestions. There are at least three IRC clients -already under development (probably more in fact. The server at -<htmlurl url="http://www.forcix.cx/irc-clients.html" -name="http://www.forcix.cx/irc-clients.html"> list a bunch of them). - -<itemize> -<item>X-Chat. -<item>girc. (Included with GNOME) -<item>gsirc. (In the gnome CVS tree) -</itemize> - -<!-- ***************************************************************** --> -<sect>How to find, configure, install, and troubleshoot GTK+ -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>What do I need to run GTK+? -<p> -To compile GTK+, all you need is a C compiler (gcc) and the X Window System -and associated libraries on your system. - -<!-- ----------------------------------------------------------------- --> -<sect1>Where can I get GTK+? -<p> -The canonical site is: -<verb> -ftp://ftp.gtk.org/pub/gtk -</verb> -This site tends to get busy around the time of a new GTK+ release -so try and use one of the mirror sites that are listed in -<htmlurl url="ftp://ftp.gtk.org/etc/mirrors" -name="ftp://ftp.gtk.org/etc/mirrors"> - -Here's a few mirror sites to get you started: -<itemize> -<item>Africa - ftp://ftp.is.co.za/applications/gimp/ -<item>Australia - ftp://ftp.au.gimp.org/pub/gimp/ -<item>Finland - ftp://ftp.funet.fi/pub/sci/graphics/packages/gimp -<item>Germany - ftp://infosoc.uni-koeln.de/pub/ftp.gimp.org/ -<item>Japan - ftp://SunSITE.sut.ac.jp/pub/archives/packages/gimp/ -<item>UK - ftp://ftp.flirble.org/pub/X/gimp/ -<item>US - ftp://ftp.insync.net/pub/mirrors/ftp.gimp.org/ -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I configure/compile GTK+? -<p> -Generally, all you will need to do is issue the commands: -<verb> -./configure -make -</verb> -in the gtk+-version/ directory. - -<!-- ----------------------------------------------------------------- --> -<sect1>When compiling GTK+ I get an error like: -<tt/make: file `Makefile' line 456: Syntax error/ -<p> -Make sure that you are using GNU make (use <tt/make -v/ to -check). There are many weird and wonderful versions of make out there, -and not all of them handle the automatically generated Makefiles. - -<!-- ----------------------------------------------------------------- --> - -<sect1>I've compiled and installed GTK+, but I can't get any programs to link with it! -<p> -This problem is most often encountered when the GTK+ libraries can't -be found or are the wrong version. Generally, the compiler will -complain about an 'unresolved symbol'. There are two things you need -to check: -<itemize> -<item>Make sure that the libraries can be found. You want to edit -/etc/ld.so.conf to include the directories which contain the GTK -libraries, so it looks something like: -<verb> -/usr/X11R6/lib -/usr/local/lib -</verb> -Then you need to run /sbin/ldconfig as root. You can find what directory -GTK is in using -<verb> -gtk-config --libs -</verb> - -If your system doesn't use ld.so to find libraries (such as Solaris), then -you will have to use the LD_LIBRARY_PATH environment variable (or compile -the path into your program, which I'm not going to cover here). So, with a -Bourne type shell you can do (if your GTK libraries are in /usr/local/lib): -<verb> -export LD_LIBRARY_PATH=/usr/local/lib -</verb> -and in a csh, you can do: -<verb> -setenv LD_LIBRARY_PATH /usr/local/lib -</verb> - -<item>Make sure the linker is finding the correct set of libraries. If you -have a Linux distribution that installs GTK+ (e.g. RedHat 5.0) then this -older version may be used. Now (assuming you have a RedHat -system), issue the command -<verb> -rpm -e gtk gtk-devel -</verb> -You may also want to remove the packages that depend on gtk (rpm will -tell you which ones they are). If you don't have a RedHat Linux -system, check to make sure that neither <verb>/usr/lib</verb> or -<verb>/usr/local/lib</verb> contain any of the libraries libgtk, -libgdk, libglib, or libgck. If they do exist, remove them (and any -gtk include files, such as /usr/include/gtk and /usr/include/gdk) and -reinstall gtk+. </itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>When compiling programs with GTK+, I get compiler error messages about not being able to find <tt/"glibconfig.h"/. -<p> -The header file "glibconfig.h" was moved to the directory -$exec_prefix/lib/glib/include/. $exec_prefix is the -directory that was specified by giving the --exec-prefix -flags to ./configure when compiling GTK+. It defaults to -$prefix, (specified with --prefix), which in turn defaults -to /usr/local/. - -This was done because "glibconfig.h" includes architecture -dependent information, and the rest of the include files -are put in $prefix/include, which can be shared between different -architectures. - -GTK+ includes a shell script, <tt/gtk-config/, that -makes it easy to find out the correct include paths. -The GTK+ tutorial includes an example of using <tt/gtk-config/ -for simple compilation from the command line. For information -about more complicated configuration, see the file -docs/gtk-config.txt in the GTK+ distribution. - -If you are trying to compile an old program, you may -be able to work around the problem by configuring it -with a command line like: - -<tscreen><verb> -CPPFLAGS="-I/usr/local/include/glib/include" ./configure -</verb></tscreen> - -for Bourne-compatible shells like bash, or for csh variants: - -<tscreen><verb> -setenv CPPFLAGS "-I/usr/local/include/glib/include" -./configure -</verb></tscreen> - -(Substitute the appropriate value of $exec_prefix for /usr/local.) - -<!-- ----------------------------------------------------------------- --> -<sect1>When installing a GTK+ application, configure reports that it can't find GTK. -<p> -There are several common reasons for this: -<itemize> -<item>You have an old version of GTK installed somewhere. RedHat 5.0, for -example, installs an older copy of GTK that may not work with the latest -applications. You should remove this old copy, but note that in the case -of RedHat 5.0 this will break the <tt/control-panel/ applications. -<P> -<item><tt/gtk-config/ (or another component of GTK) isn't in your path, or -there is an old version on your system. Type: -<verb> -gtk-config --version -</verb> -to check for both of these. If it returns a value different from what -you expect, then you have an old version of GTK on your system. -<P> -<item>The ./configure script can't find the GTK libraries. As ./configure -compiles various test programs, it needs to be able to find the GTK -libraries. See the question above for help on this. -</itemize> -<p> -If none of the above help, then have a look in config.log, which is -generated by ./configure as it runs. At the bottom will be the last -action it took before failing. If it is a section of source code, copy -the source code to a file and compile it with the line just above it in -config.log. If the compilation is successful, try executing it. - -<!-- ***************************************************************** --> -<sect>Development of GTK+ -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Whats this CVS thing that everyone keeps talking about, and how do I access it? -<p> -CVS is the Concurent Version System and is a very popular means of -version control for software projects. It is designed to allow multiple -authors to be able to simultanously operate on the same source tree. -This source tree is centrally maintained, but each developer has a -local mirror of this repository that they make there changes to. - -The GTK+ developers use a CVS repository to store the master copy of -the current development version of GTK+. As such, people wishing to -contribute patches to GTK+ should generate them against the CVS version. -Normal people should use the packaged releases. - -The CVS toolset is available as RPM packages from the usual RedHat sites. -The latest version is available at -<htmlurl url="http://download.cyclic.com/pub/" -name="http://download.cyclic.com/pub/"> - -Anyone can download the latest CVS version of GTK+ by using anonymous access -using the following steps: -<itemize> -<item> In a bourne shell descendant (e.g. bash) type: -<verb> -CVSROOT=':pserver:anonymous@anoncvs.gnome.org:/cvs/gnome' -export CVSROOT -</verb> -<item>Next, the first time the source tree is checked out, a cvs login -is needed. -<verb> -cvs login -</verb> -This will ask you for a password. There is no password for cvs.gimp.org, -so just enter a carriage return. -<item>To get the tree and place it in a subdir of your current working -directory, issue the command: -<verb> -cvs -z3 get gtk+ -</verb> - -Note that with the GTK+ 1.1 tree, glib has been moved to a separate CVS -module, so if you don't have glib installed you will need to get that -as well: -<verb> -cvs -z3 get glib -</verb> -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>How can I contribute to GTK+? -<p> -It's simple. If something doesn't work like you think it should in a program, -check the documentation to make sure you're not missing something. If it is a -true bug or missing feature, track it down in the GTK+ source, change it, -and then generate a patch in the form of a 'context diff'. This can be done -using a command such as <tt/diff -ru <oldfile> <newfile>/. -Then upload the patchfile to: -<verb> -ftp://ftp.gtk.org/incoming -</verb> -along with a README file. Make sure you follow the naming conventions or your -patch will just be deleted! The filenames should be of this form: -<verb> -gtk-<username>-<date yymmdd-n>.patch.gz -gtk-<username>-<date yymmdd-n>.patch.README -</verb> -The "n" in the date indicates a unique number (starting from 0) -of patches you uploaded that day. It should be 0, unless you -upload more than one patch in the same day. - -Example: -<verb> -gtk-gale-982701-0.patch.gz -gtk-gale-982701-0.patch.README -</verb> -Once you upload <em>anything</em>, send the README to ftp-admin@gtk.org - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I know if my patch got applied, and if not, why not? -<p> -Uploaded patches will be moved to <tt>ftp://ftp.gtk.org/pub/gtk/patches</tt> -where one of the GTK+ development team will pick them up. If applied, they -will be moved to <tt>/pub/gtk/patches/old</tt>. - -Patches that aren't applied, for whatever reason, are moved to -<tt>/pub/gtk/patches/unapplied</tt> or <tt>/pub/gtk/patches/outdated</tt>. -At this point you can ask on the <tt/gtk-list/ mailing list why your patch -wasn't applied. There are many possible reasons why patches may not be -applied, ranging from it doesn't apply cleanly, to it isn't right. Don't -be put off if your patch didn't make it first time round. - -<!-- ----------------------------------------------------------------- --> -<sect1>What is the policy on incorporating new widgets into the library? -<p> -This is up to the authors, so you will have to ask them once you -are done with your widget. As a general guideline, widgets that are -generally useful, work, and are not a disgrace to the widget set will -gladly be included. - -<!-- ----------------------------------------------------------------- --> -<sect1>Is anyone working on bindings for languages other than C? -<p> -The GTK+ home page (<htmlurl url="http://www.gtk.org/" -name="http://www.gtk.org/">) presents a list of GTK+ bindings. - -<itemize> -<item>There are several C++ wrappers for GTK+. - <itemize> - - <item>the gtk-- package, which is a very small wrapper for GTK+. - You can find the home page at: - <htmlurl url="http://www.cs.tut.fi/~p150650/gtk/gtk--.html" - name="http://www.cs.tut.fi/~p150650/gtk/gtk--.html">. - The FTP site is - <htmlurl url="ftp://ftp.gtk.org/pub/gtk/gtk--" - name="ftp://ftp.gtk.org/pub/gtk/gtk--">. - - <item>the VDK package, which was built as the base package of a GTK+ - application Borland-like builder. The home page can be found at - <htmlurl url="www.guest.net/homepages/mmotta/VDKHome" - name="www.guest.net/homepages/mmotta/VDKHome">. - - <item>The wxWindows/Gtk package, a free C++ library for cross-platform - GUI development. The home page of this package is - <htmlurl url="http://www.freiburg.linux.de/~wxxt/" - name="http://www.freiburg.linux.de/~wxxt/">. - - </itemize> -<p> - -<item>There are three known Objective-c bindings currently in development: - - <itemize> - - <item>The <htmlurl url="http://www.gnome.org/" name="GNOME project's"> package - of choice is objgtk. Objgtk is based on the Object class and is maintained by - <htmlurl url="mailto:sopwith@cuc.edu" name="Elliot Lee">. Apparently, objgtk - is being accepted as the `standard' Objective-C binding for GTK+. - - <item>If you are more inclined towards the - <htmlurl url="http://www.gnustep.org/" name="GNUstep project">, - you may want to check out GTKKit by - <htmlurl url="mailto:helge@mdlink.de" name="Helge Heß">. - The intention is to setup a GTK+ binding using the FoundationKit. - GTKKit includes nicities like writing a XML-type template file to - construct a GTK+ interface. - - <item>The GToolKit package, which can be found at - <htmlurl url="ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/" - name="ftp://ftp.gtk.org/pub/gtk/objc-gtoolkit/">. - - </itemize> -<p> -<item>Perl bindings - <htmlurl url="ftp://ftp.gtk.org/pub/gtk/perl" - name="ftp://ftp.gtk.org/pub/gtk/perl"> -<P> -<item>Guile bindings. The home page is at - <htmlurl url="http://www.ping.de/sites/zagadka/guile-gtk" - name="http://www.ping.de/sites/zagadka/guile-gtk">. - By the way, Guile is the GNU Project's implemention of R4RS Scheme (the - standard). If you like Scheme, you may want to take a look at this. -<p> - -<item>David Monniaux reports: - <quote>I've started a gtk-O'Caml binding system. - The basics of the system, including callbacks, work fine. - - The current development is in - <htmlurl url="http://www.ens-lyon.fr/~dmonniau/arcs" - name="http://www.ens-lyon.fr/~dmonniau/arcs"> - </quote> - -<item> Several python bindings have been done: -<p> - <itemize> - <item>pygtk is at - <htmlurl url="http://www.daa.com.au/~james/pygtk" - name="http://www.daa.com.au/~james/pygtk"> and - <htmlurl url="ftp://ftp.gtk.org/pub/gtk/python" - name="ftp://ftp.gtk.org/pub/gtk/python"> - - <item>python-gtk is at - <htmlurl url="http://www.ucalgary.ca/~nascheme/python-gtk" - name="http://www.ucalgary.ca/~nascheme/python-gtk"> - </itemize> -<p> -<item>There's are a couple of OpenGL/Mesa widgets available for -GTK+. I suggest you start at - <htmlurl url="http://www.student.oulu.fi/~jlof/gtkglarea/index.html" - name="http://www.student.oulu.fi/~jlof/gtkglarea/index.html"> -<p> -<item>Last, there are a lot of other language bindings for languages such as - Eiffel, TOM, Pascal, Pike, etc. - -</itemize> - -<!-- ***************************************************************** --> -<sect>Development with GTK+: the begining -<!-- ***************************************************************** --> - - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I get started? -<p> -So, after you have installed GTK+ there are a couple of things that can -ease you into developing applications with it. There is the -GTK+ Tutorial <htmlurl url="http://www.gtk.org/tutorial/" -name="http://www.gtk.org/tutorial/">, which is undergoing -development. This will introduce you to writing applications using C. - -The Tutorial doesn't (yet) contain information on all of the widgets -that are in GTK+. For example code on how to use the basics of all the -GTK+ widgets you should look at the file gtk/testgtk.c (and associated -source files) within the GTK+ distribution. Looking at these examples will -give you a good grounding on what the widgets can do. - -<!-- ----------------------------------------------------------------- --> -<sect1>I tried to compile a small <tt/Hello World/ of mine, but it failed. Any clue? -<p> -Since you are good at coding, we will not deal with compile time error here :). - -The classic command line to compile a GTK+ based program is - -<verb> -gcc -o myprg [c files list] `gtk-config --cflags --libs` -</verb> - -You should notice the backquote character which is used in this command line. -A common mistake when you start a GTK+ based development is to use quote -instead of backquotes. If you do so, the compiler will complain about an -unknown file called 'gtk-config --cflags --libs'. The text in -backquotes is an instruction to your shell to substitute the output of -executing this text into the command line. - -The command line above ensure that: -<itemize> - - <item>the correct C compiler flags will be used to compile the program - (including the complete C header directory list) - - <item>your program will be linked with the needed libraries. - -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>What about using the <tt/make/ utility? -<p> -This is a sample makefile which compile a GTK+ based program: - -<tscreen><verb> -# basic GTK+ app makefile -SOURCES = myprg.c foo.c bar.c -OBJS = ${SOURCES:.c=.o} -CFLAGS = `gtk-config --cflags` -LDADD = `gtk-config --libs` -CC = gcc -PACKAGE = myprg - -all : ${OBJS} - ${CC} -o ${PACKAGE} ${OBJS} ${LDADD} - -.c.o: - ${CC} ${CFLAGS} -c $< - -# end of file -</verb></tscreen> - -For more information about the <tt/make/ utility, you should read either the -related man page or the relevant info file. - -<sect1>I use the backquote stuff in my makefiles, but my make process failed. -<p> -The backquote construction seems to not be accepted by some old <tt/make/ -utilities. If you use one of these, the make process will probably fail. -In order to have the backquote syntax working again, you should use the -GNU make utility (get it on the GNU ftp server at -<htmlurl url="ftp://ftp.gnu.org/" name="ftp://ftp.gnu.org/">). - -<!-- ----------------------------------------------------------------- --> -<sect1>I want to add some configure stuff, how could I do this? -<p> -To use autoconf/automake, you must first install the relevant packages. These -are: - -<itemize> - <item>the m4 preprocessor v1.4 or better - <item>autoconf v2.13 or better - <item>automake v1.4 or better -</itemize> - -You'll find these packages on the GNU main ftp server (<htmlurl -url="ftp://ftp.gnu.org/" name="ftp://ftp.gnu.org/">) or on any GNU mirror. - -In order to use the powerful autoconf/automake scheme, you must create -a configure.in which may look like: - -<tscreen><verb> -dnl Process this file with autoconf to produce a configure script. -dnl configure.in for a GTK+ based program - -AC_INIT(myprg.c)dnl -AM_INIT_AUTOMAKE(mypkgname,0.0.1)dnl -AM_CONFIG_HEADER(config.h)dnl - -dnl Checks for programs. -AC_PROG_CC dnl check for the c compiler -dnl you should add CFLAGS="" here, 'cos it is set to -g by PROG_CC - -dnl Checks for libraries. -AM_PATH_GTK(1.2.0,,AC_MSG_ERROR(mypkgname 0.1 needs GTK))dnl - -AC_OUTPUT( - Makefile -)dnl -</verb></tscreen> - -You must add a Makefile.am file: - -<tscreen><verb> -bin_PROGRAMS = myprg -myprg_SOURCES = myprg.c foo.c bar.c -INCLUDES = @GTK_CFLAGS@ -LDADD = @GTK_LIBS@ -CLEANFILES = *~ -DISTCLEANFILES = .deps/*.P -</verb></tscreen> - -If your project contains more than one subdirectory, you'll have to -create one Makefile.am in each directory plus a master Makefile.am -which will look like: - -<tscreen><verb> -SUBDIRS = mydir1 mydir2 mydir3 -</verb></tscreen> - -then, to use these, simply type the following commands: - -<verb> -aclocal -autoheader -autoconf -automake --add-missing --include-deps --foreign -</verb> - -For further information, you should look at the autoconf and the -automake documentation (the shipped info files are really easy to -understand, and there are plenty of web resources that deal with -autoconf and automake). - -<!-- ----------------------------------------------------------------- --> -<sect1>I try to debug my GTK+ application with gdb, but it hangs my X server when I hit some breakpoint. Any Idea ? -<p> -From Federico Mena Quintero: -<quote> -X is not locked up. It is likely that you are hitting a breakpoint -inside a callback that is called from a place in Gtk that has a mouse -grab. -<P> -Run your program with the "--sync" option; it will make it easier to -debug. Also, you may want to use the console for running the -debugger, and just let the program run in another console with the X -server. -</quote> - -Eric Mouw had another solution: -<quote> -An old terminal connected to an otherwise unused serial port is also great -for debugging X programs. Old vt100/vt220 terminals are dirt cheap but a -bit hard to get (here in The Netherlands, YMMV). -</quote> - -<!-- ***************************************************************** --> -<sect>Development with GTK+: general questions -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>What widgets are in GTK? -<p> -The GTK+ Tutorial lists the following widgets: - -<verb> - GtkObject - +GtkData - | +GtkAdjustment - | `GtkTooltips - `GtkWidget - +GtkContainer - | +GtkBin - | | +GtkAlignment - | | +GtkEventBox - | | +GtkFrame - | | | `GtkAspectFrame - | | +GtkHandleBox - | | +GtkItem - | | | +GtkListItem - | | | +GtkMenuItem - | | | | `GtkCheckMenuItem - | | | | `GtkRadioMenuItem - | | | `GtkTreeItem - | | +GtkViewport - | | `GtkWindow - | | +GtkColorSelectionDialog - | | +GtkDialog - | | | `GtkInputDialog - | | `GtkFileSelection - | +GtkBox - | | +GtkButtonBox - | | | +GtkHButtonBox - | | | `GtkVButtonBox - | | +GtkHBox - | | | +GtkCombo - | | | `GtkStatusbar - | | `GtkVBox - | | +GtkColorSelection - | | `GtkGammaCurve - | +GtkButton - | | +GtkOptionMenu - | | `GtkToggleButton - | | `GtkCheckButton - | | `GtkRadioButton - | +GtkCList - | `GtkCTree - | +GtkFixed - | +GtkList - | +GtkMenuShell - | | +GtkMenuBar - | | `GtkMenu - | +GtkNotebook - | +GtkPaned - | | +GtkHPaned - | | `GtkVPaned - | +GtkScrolledWindow - | +GtkTable - | +GtkToolbar - | `GtkTree - +GtkDrawingArea - | `GtkCurve - +GtkEditable - | +GtkEntry - | | `GtkSpinButton - | `GtkText - +GtkMisc - | +GtkArrow - | +GtkImage - | +GtkLabel - | | `GtkTipsQuery - | `GtkPixmap - +GtkPreview - +GtkProgressBar - +GtkRange - | +GtkScale - | | +GtkHScale - | | `GtkVScale - | `GtkScrollbar - | +GtkHScrollbar - | `GtkVScrollbar - +GtkRuler - | +GtkHRuler - | `GtkVRuler - `GtkSeparator - +GtkHSeparator - `GtkVSeparator -</verb> - -<!-- ----------------------------------------------------------------- --> -<sect1>Is GTK+ thread safe? How do I write multi-threaded GTK+ applications? -<p> -The GLib library can be used in a thread-safe mode by calling -g_thread_init() before making any other GLib calls. In this mode GLib -automatically locks all internal data structures as needed. This -does not mean that two threads can simultaneously access, for -example, a single hash table, but they can access two different hash -tables simultaneously. If two different threads need to access the -same hash table, the application is responsible for locking -itself. - -When GLib is intialized to be thread-safe, GTK+ is -<em>thread aware</em>. There is a single global lock -that you must acquire with gdk_threads_enter() before -making any GDK calls, and release with gdk_threads_leave() -afterwards. - -A minimal main program for a threaded GTK+ application -looks like: - -<verb> -int -main (int argc, char *argv[]) -{ - GtkWidget *window; - - g_thread_init(NULL); - gtk_init(&argc, &argv); - - window = create_window(); - gtk_widget_show(window); - - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return(0); -} -</verb> - -Callbacks require a bit of attention. Callbacks from GTK+ -(signals) are made within the GTK+ lock. However callbacks -from GLib (timeouts, IO callbacks, and idle functions) -are made outside of the GTK+ lock. So, within a signal -handler you do not need to call gdk_threads_enter(), but -within the other types of callbacks, you do. - -Erik Mouw contributed the following code example to illustrate how to -use threads within GTK+ programs. - -<tscreen><verb> -/*------------------------------------------------------------------------- - * Filename: gtk-thread.c - * Version: 0.99.1 - * Copyright: Copyright (C) 1999, Erik Mouw - * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Description: GTK threads example. - * Created at: Sun Oct 17 21:27:09 1999 - * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Modified at: Sun Oct 24 17:21:41 1999 - *-----------------------------------------------------------------------*/ -/* - * Compile with: - * - * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread` - * - * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some - * bugs. - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <time.h> -#include <gtk/gtk.h> -#include <glib.h> -#include <pthread.h> - -#define YES_IT_IS (1) -#define NO_IT_IS_NOT (0) - -typedef struct -{ - GtkWidget *label; - int what; -} yes_or_no_args; - -G_LOCK_DEFINE_STATIC (yes_or_no); -static volatile int yes_or_no = YES_IT_IS; - -void destroy(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -void *argument_thread(void *args) -{ - yes_or_no_args *data = (yes_or_no_args *)args; - gboolean say_something; - - for(;;) - { - /* sleep a while */ - sleep(rand() / (RAND_MAX / 3) + 1); - - /* lock the yes_or_no_variable */ - G_LOCK(yes_or_no); - - /* do we have to say something? */ - say_something = (yes_or_no != data->what); - - if(say_something) - { - /* set the variable */ - yes_or_no = data->what; - } - - /* Unlock the yes_or_no variable */ - G_UNLOCK(yes_or_no); - - if(say_something) - { - /* get GTK thread lock */ - gdk_threads_enter(); - - /* set label text */ - if(data->what == YES_IT_IS) - gtk_label_set_text(GTK_LABEL(data->label), "O yes, it is!"); - else - gtk_label_set_text(GTK_LABEL(data->label), "O no, it isn't!"); - - /* release GTK thread lock */ - gdk_threads_leave(); - } - } - - return(NULL); -} - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *label; - yes_or_no_args yes_args, no_args; - pthread_t no_tid, yes_tid; - - /* init threads */ - g_thread_init(NULL); - - /* init gtk */ - gtk_init(&argc, &argv); - - /* init random number generator */ - srand((unsigned int)time(NULL)); - - /* create a window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect(GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(destroy), NULL); - - gtk_container_set_border_width(GTK_CONTAINER (window), 10); - - /* create a label */ - label = gtk_label_new("And now for something completely different ..."); - gtk_container_add(GTK_CONTAINER(window), label); - - /* show everything */ - gtk_widget_show(label); - gtk_widget_show (window); - - /* create the threads */ - yes_args.label = label; - yes_args.what = YES_IT_IS; - pthread_create(&yes_tid, NULL, argument_thread, &yes_args); - - no_args.label = label; - no_args.what = NO_IT_IS_NOT; - pthread_create(&no_tid, NULL, argument_thread, &no_args); - - /* enter the GTK main loop */ - gdk_threads_enter(); - gtk_main(); - gdk_threads_leave(); - - return(0); -} -</verb></tscreen> - -<!-- This is the old answer - TRG - -Although GTK+, like many X toolkits, isn't thread safe, this does -not prohibit the development of multi-threaded applications with -GTK+. - -Rob Browning (rlb@cs.utexas.edu) describes threading techniques for -use with GTK+ (slightly edited): - -There are basically two main approaches, the first is simple, and the -second complicated. In the first, you just make sure that all GTK+ (or -X) interactions are handled by one, and -only one, thread. Any other thread that wants to draw something has -to somehow notify the "GTK+" thread, and let it handle the -actual work. - -The second approach allows you to call GTK+ (or X) functions from any -thread, but it requires some careful synchronization. The -basic idea is that you create an X protection mutex, and no one may -make any X calls without first acquiring this mutex. - -Note that this is a little effort, but it allows you to be -potentially more efficient than a completely thread safe GTK+. You -get to decide the granularity of the thread locking. You also have to -make sure that the thread that calls <tt/gtk_main()/ is holding the lock when -it calls <tt/gtk_main()/. - -The next thing to worry about is that since you were holding the -global mutex when you entered <tt/gtk_main()/, all callbacks will also be -holding it. This means that the callback must release it if it's -going to call any other code that might reacquire it. Otherwise -you'll get deadlock. Also, you must be holding the mutex when you -finally return from the callback. - -In order to allow threads other than the one calling <tt/gtk_main/ to -get access to the mutex, we also need to register a work function -with GTK that allows us to release the mutex periodically. - -Why can't GTK+ be thread safe by default? - -Complexity, overhead, and manpower. The proportion of threaded -programs is still reasonably small, and getting thread safety right is -both quite difficult and takes valuable time away from the main work -of getting a good graphics library finished. It would be nice to have -GTK+ thread safe "out of the box", but that's not practical right now, -and it also might make GTK+ substantially less efficient if not handled -carefully. - -Regardless, it's especially not a priority since relatively good -workarounds exist. ---> - -<!-- ----------------------------------------------------------------- --> -<sect1>Why does this strange 'x io error' occur when I <tt/fork()/ in my GTK+ app? -<p> -This is not really a GTK+ problem, and the problem is not related to -<tt/fork()/ either. If the 'x io error' occurs then you probably use -the <tt/exit()/ function in order to exit from the child process. - -When GDK opens an X display, it creates a socket file descriptor. When -you use the <tt/exit()/ function, you implicitly close all the open -file descriptors, and the underlying X library really doesn't like -this. - -The right function to use here is <tt/_exit()/. - -Erik Mouw contributed the following code example to illustrate -handling fork() and exit(). - -<tscreen><verb> -/*------------------------------------------------------------------------- - * Filename: gtk-fork.c - * Version: 0.99.1 - * Copyright: Copyright (C) 1999, Erik Mouw - * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Description: GTK+ fork example - * Created at: Thu Sep 23 21:37:55 1999 - * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl> - * Modified at: Thu Sep 23 22:39:39 1999 - *-----------------------------------------------------------------------*/ -/* - * Compile with: - * - * cc -o gtk-fork gtk-fork.c `gtk-config --cflags --libs` - * - */ - -#include <stdio.h> -#include <stdlib.h> -#include <signal.h> -#include <sys/types.h> -#include <sys/wait.h> -#include <unistd.h> -#include <gtk/gtk.h> - -void sigchld_handler(int num) -{ - sigset_t set, oldset; - pid_t pid; - int status, exitstatus; - - /* block other incoming SIGCHLD signals */ - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - sigprocmask(SIG_BLOCK, &set, &oldset); - - /* wait for child */ - while((pid = waitpid((pid_t)-1, &status, WNOHANG)) > 0) - { - if(WIFEXITED(status)) - { - exitstatus = WEXITSTATUS(status); - - fprintf(stderr, - "Parent: child exited, pid = %d, exit status = %d\n", - (int)pid, exitstatus); - } - else if(WIFSIGNALED(status)) - { - exitstatus = WTERMSIG(status); - - fprintf(stderr, - "Parent: child terminated by signal %d, pid = %d\n", - exitstatus, (int)pid); - } - else if(WIFSTOPPED(status)) - { - exitstatus = WSTOPSIG(status); - - fprintf(stderr, - "Parent: child stopped by signal %d, pid = %d\n", - exitstatus, (int)pid); - } - else - { - fprintf(stderr, - "Parent: child exited magically, pid = %d\n", - (int)pid); - } - } - - /* re-install the signal handler (some systems need this) */ - signal(SIGCHLD, sigchld_handler); - - /* and unblock it */ - sigemptyset(&set); - sigaddset(&set, SIGCHLD); - sigprocmask(SIG_UNBLOCK, &set, &oldset); -} - -gint delete_event(GtkWidget *widget, GdkEvent *event, gpointer data) -{ - return(FALSE); -} - -void destroy(GtkWidget *widget, gpointer data) -{ - gtk_main_quit(); -} - -void fork_me(GtkWidget *widget, gpointer data) -{ - pid_t pid; - - pid = fork(); - - if(pid == -1) - { - /* ouch, fork() failed */ - perror("fork"); - exit(-1); - } - else if(pid == 0) - { - /* child */ - fprintf(stderr, "Child: pid = %d\n", (int)getpid()); - - execlp("ls", "ls", "-CF", "/", NULL); - - /* if exec() returns, there is something wrong */ - perror("execlp"); - - /* exit child. note the use of _exit() instead of exit() */ - _exit(-1); - } - else - { - /* parent */ - fprintf(stderr, "Parent: forked a child with pid = %d\n", (int)pid); - } -} - -int main(int argc, char *argv[]) -{ - GtkWidget *window; - GtkWidget *button; - - gtk_init(&argc, &argv); - - /* the basic stuff: make a window and set callbacks for destroy and - * delete events - */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - - gtk_signal_connect(GTK_OBJECT (window), "delete_event", - GTK_SIGNAL_FUNC(delete_event), NULL); - - gtk_signal_connect(GTK_OBJECT (window), "destroy", - GTK_SIGNAL_FUNC(destroy), NULL); - -#if (GTK_MAJOR_VERSION == 1) && (GTK_MINOR_VERSION == 0) - gtk_container_border_width(GTK_CONTAINER (window), 10); -#else - gtk_container_set_border_width(GTK_CONTAINER (window), 10); -#endif - - /* add a button to do something useful */ - button = gtk_button_new_with_label("Fork me!"); - - gtk_signal_connect(GTK_OBJECT (button), "clicked", - GTK_SIGNAL_FUNC(fork_me), NULL); - - gtk_container_add(GTK_CONTAINER(window), button); - - /* show everything */ - gtk_widget_show (button); - gtk_widget_show (window); - - - /* install a signal handler for SIGCHLD signals */ - signal(SIGCHLD, sigchld_handler); - - - /* main loop */ - gtk_main (); - - exit(0); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Why don't the contents of a button move when the button is pressed? Here's a patch to make it work that way... -<p> -From: Peter Mattis - -<quote> -The reason buttons don't move their child down and to the right when -they are depressed is because I don't think that's what is happening -visually. My view of buttons is that you are looking at them straight -on. That is, the user interface lies in a plane and you're above it -looking straight at it. When a button gets pressed it moves directly -away from you. To be absolutely correct I guess the child should -actually shrink a tiny amount. But I don't see why the child should -shift down and to the left. Remember, the child is supposed to be -attached to the buttons surface. Its not good for it to appear like -the child is slipping on the surface of the button. -<P> -On a more practical note, I did implement this at one point and -determined it didn't look good and removed it. -</quote> - -<!-- ----------------------------------------------------------------- --> -<sect1>How to I identifiy a widgets top level window or other ancestor? -<p> -There are a couple of ways to find the top level parent of a -widget. The easier way is to call the <tt/gtk_widget_top_level()/ -function that returns a pointer to a GtkWidget that is the top level -window. - -A more complicated way to do this (but less limited, as it allows -the user to get the closest ancestor of a known type) is to use -<tt/gtk_widget_get_ancestor()/ as in: - -<tscreen><verb> - GtkWidget *widget; - - widget = gtk_widget_get_ancestor(w, GTK_TYPE_WINDOW); -</verb></tscreen> - -Since virtually all the GTK_TYPEs can be used as the second parameter -of this function, you can get any parent widget of a particular -widget. Suppose you have an hbox which contains a vbox, which in turn -contains some other atomic widget (entry, label, etc. To find the -master hbox using the <tt/entry/ widget simply use: - -<tscreen><verb> - GtkWidget *hbox; - hbox = gtk_widget_get_ancestor(w, GTK_TYPE_HBOX); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I get the Window ID of a GtkWindow? -<p> -The actual Gdk/X window will be created when the widget gets -realized. You can get the Window ID with: - -<verb> -#include <gdk/gdkx.h> - -Window xwin = GDK_WINDOW_XWINDOW (GTK_WIDGET (my_window)->window); -</verb> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I catch a double click event (in a list widget, for example)? -<p> -Tim Janik wrote to gtk-list (slightly modified): - -Define a signal handler: - -<tscreen><verb> -gint -signal_handler_event(GtkWiget *widget, GdkEvenButton *event, gpointer func_data) -{ - if (GTK_IS_LIST_ITEM(widget) && - (event->type==GDK_2BUTTON_PRESS || - event->type==GDK_3BUTTON_PRESS) ) { - printf("I feel %s clicked on button %d\", - event->type==GDK_2BUTTON_PRESS ? "double" : "triple", - event->button); - } - - return FALSE; -} -</verb></tscreen> - -And connect the handler to your object: - -<tscreen><verb> -{ - /* list, list item init stuff */ - - gtk_signal_connect(GTK_OBJECT(list_item), - "button_press_event", - GTK_SIGNAL_FUNC(signal_handler_event), - NULL); - - /* and/or */ - - gtk_signal_connect(GTK_OBJECT(list_item), - "button_release_event", - GTK_SIGNAL_FUNC(signal_handler_event), - NULL); - - /* something else */ -} -</verb></tscreen> - -and, Owen Taylor wrote: - -Note that a single button press will be received beforehand, and -if you are doing this for a button, you will therefore also get a -"clicked" signal for the button. (This is going to be true for -any toolkit, since computers aren't good at reading one's -mind.) - -<!-- ----------------------------------------------------------------- --> -<sect1>By the way, what are the differences between signals and events? -<p> -First of all, Havoc Pennington gives a rather complete description of -the differences between events and signals in his free book (two -chapters can be found at <htmlurl -url="http://www106.pair.com/rhp/sample_chapters.html" -name="http://www106.pair.com/rhp/sample_chapters.html">). - -Moreover, Havoc posted this to the <tt/gtk-list/ -<quote> - Events are a stream of messages received from the X server. They - drive the Gtk main loop; which more or less amounts to "wait for - events, process them" (not exactly, it is really more general than - that and can wait on many different input streams at once). Events - are a Gdk/Xlib concept. -<P> - Signals are a feature of GtkObject and its subclasses. They have - nothing to do with any input stream; really a signal is just a way - to keep a list of callbacks around and invoke them ("emit" the - signal). There are lots of details and extra features of - course. Signals are emitted by object instances, and are entirely - unrelated to the Gtk main loop. Conventionally, signals are emitted - "when something changes" about the object emitting the signal. -<P> - Signals and events only come together because GtkWidget happens to - emit signals when it gets events. This is purely a convenience, so - you can connect callbacks to be invoked when a particular widget - receives a particular event. There is nothing about this that makes - signals and events inherently related concepts, any more than - emitting a signal when you click a button makes button clicking and - signals related concepts. -</quote> - -<!-- ----------------------------------------------------------------- --> -<sect1>Data I pass to the <tt/delete_event/ (or other event) handler gets corrupted. -<p> -All event handlers take an additional argument which contains -information about the event that triggered the handler. So, a -<tt/delete_event/ handler must be declared as: - -<tscreen><verb> -gint delete_event_handler (GtkWidget *widget, - GdkEventAny *event, - gpointer data); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>I have my signal connected to the the (whatever) event, but it seems I don't catch it. What's wrong? -<p> -There is some special initialisation to do in order to catch some -particular events. In fact, you must set the correct event mask bit of -your widget before getting some particular events. - -For example, - -<tscreen><verb> - gtk_widget_add_events(window, GDK_KEY_RELEASE_MASK); -</verb></tscreen> - -lets you catch the key release events. If you want to catch every events, -simply us the GDK_ALL_EVENTS_MASK event mask. - -All the event masks are defined in the <tt/gdktypes.h/ file. - -<!-- ----------------------------------------------------------------- --> -<sect1>I need to add a new signal to a GTK+ widget. Any idea? -<p> -If the signal you want to add may be beneficial for other GTK+ users, -you may want to submit a patch that presents your changes. Check the -tutorial for more information about adding signals to a widget class. - -If you don't think it is the case or if your patch is not applied -you'll have to use the <tt/gtk_object_class_user_signal_new/ -function. <tt/gtk_object_class_user_signal_new/ allows you to add a -new signal to a predefined GTK+ widget without any modification of the -GTK+ source code. The new signal can be emited with -<tt/gtk_signal_emit/ and can be handled in the same way as other -signals. - -Tim Janik posted this code snippet: - -<tscreen><verb> -static guint signal_user_action = 0; - -signal_user_action = - gtk_object_class_user_signal_new (gtk_type_class (GTK_TYPE_WIDGET), - "user_action", - GTK_RUN_LAST | GTK_RUN_ACTION, - gtk_marshal_NONE__POINTER, - GTK_TYPE_NONE, 1, - GTK_TYPE_POINTER); - -void -gtk_widget_user_action (GtkWidget *widget, - gpointer act_data) -{ - g_return_if_fail (GTK_IS_WIDGET (widget)); - - gtk_signal_emit (GTK_OBJECT (widget), signal_user_action, act_data); -} -</verb></tscreen> - -If you want your new signal to have more than the classical gpointer -parameter, you'll have to play with GTK+ marshallers. - -<!-- ----------------------------------------------------------------- --> -<sect1>Is it possible to get some text displayed which is truncated to fit inside its allocation? -<p> -GTK's behavior (no clipping) is a consequence of its attempts to -conserve X resources. Label widgets (among others) don't get their own -X window - they just draw their contents on their parent's window. -While it might be possible to have clipping occur by setting the clip -mask before drawing the text, this would probably cause a substantial -performance penalty. - -Its possible that, in the long term, the best solution to such -problems might be just to change gtk to give labels X windows. -A short term workaround is to put the label widget inside another -widget that does get its own window - one possible candidate would -be the viewport widget. - -<tscreen><verb> -viewport = gtk_viewport (NULL, NULL); -gtk_widget_set_usize (viewport, 50, 25); -gtk_viewport_set_shadow_type (GTK_VIEWPORT(viewport), GTK_SHADOW_NONE); -gtk_widget_show(viewport); - -label = gtk_label ("a really long label that won't fit"); -gtk_container_add (GTK_CONTAINER(viewport), label); -gtk_widget_show (label); -</verb></tscreen> - -If you were doing this for a bunch of widgets, you might want to -copy gtkviewport.c and strip out the adjustment and shadow -functionality (perhaps you could call it GtkClipper). - -<!-- ----------------------------------------------------------------- --> - -<sect1>How do I make my window modal? / How do I make a single window active? -<p> -After you create your window, do <tt/gtk_grab_add(my_window)/. And after -closing the window do <tt/gtk_grab_remove(my_window)/. - -<!-- ----------------------------------------------------------------- --> -<sect1>Why doesn't my widget (e.g. progressbar) update? -<p> - -You are probably doing all the changes within a function without -returning control to <tt/gtk_main()/. This may be the case if you do -some lengthy calculation in your code. Most drawing updates are only -placed on a queue, which is processed within <tt/gtk_main()/. You can -force the drawing queue to be processed using something like: - -<tscreen><verb> -while (g_main_iteration(FALSE)); -</verb></tscreen> - -inside you're function that changes the widget. - -What the above snippet does is run all pending events and high priority -idle functions, then return immediately (the drawing is done in a -high priority idle function). - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I attach data to some GTK+ object/widget? -<p> -First of all, the attached data is stored in the object_data field of -a GtkObject. The type of this field is GData, which is defined in -glib.h. So you should read the gdataset.c file in your glib source -directory very carefully. - -There are two (easy) ways to attach some data to a gtk object. Using -<tt/gtk_object_set_data()/ and <tt/gtk_object_get_data()/ seems to be -the most common way to do this, as it provides a powerful interface to -connect objects and data. - -<tscreen><verb> -void gtk_object_set_data(GtkObject *object, const gchar *key, gpointer data); - -gpointer gtk_object_get_data(GtkObject *object, const gchar *key); -</verb></tscreen> - -Since a short example is better than any lengthy speech: - -<tscreen><verb> -struct my_struct p1,p2,*result; -GtkWidget *w; - -gtk_object_set_data(GTK_OBJECT(w),"p1 data",(gpointer)&p1); -gtk_object_set_data(GTK_OBJECT(w),"p2 data",(gpointer)&p2); - -result = gtk_object_get_data(GTK_OBJECT(w),"p1 data"); -</verb></tscreen> - -The <tt/gtk_object_set_user_data()/ and <tt/gtk_object_get_user_data()/ -functions does exactly the same thing -as the functions above, but does not let you specify the "key" parameter. -Instead, it uses a standard "user_data" key. Note that the use of these -functions is deprecated in 1.2. They only provide a compatibility mode -with some old gtk packages. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I remove the data I have attached to an object? -<p> -When attaching the data to the object, you can use the -<tt/gtk_object_set_data_full()/ function. The three first arguments of -the function are the same as in <tt/gtk_object_set_data()/. The fourth -one is a pointer to a callback function which is called when the data -is destroyed. The data is destroyed when you: - -<itemize> -<item> destroy the object -<item> replace the data with a new one (with the same key) -<item> replace the data with NULL (with the same key) -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I reparent a widget? -<p> -The normal way to reparent (ie change the owner) of a widget should be -to use the function: - -<tscreen><verb> -void gtk_widget_reparent (GtkWidget *widget, - GtkWidget *new_parent) -</verb></tscreen> - -But this is only a "should be" since this function does not correctly -do its job on some specific widgets. The main goal of -gtk_widget_reparent() is to avoid unrealizing widget if both widget -and new_parent are realized (in this case, widget->window is -successfully reparented). The problem here is that some widgets in the -GTK+ hierarchy have multiple attached X subwindows and this is notably -the case for the GtkSpinButton widget. For those, -gtk_widget_reparent() will fail by leaving an unrealized child window -where it should not. - -To avoid this problem, simply use the following code snippet: - -<tscreen><verb> - gtk_widget_ref(widget); - gtk_container_remove(GTK_CONTAINER(old_parent), widget); - gtk_container_add(GTK_CONTAINER(new_parent), widget); - gtk_widget_unref(widget); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How could I get any widgets position? -<p> -As Tim Janik pointed out, there are different cases, and each case -requires a different solution. - -<itemize> -<item> If you want the position of a widget relative to its parent, - you should use <tt/widget->allocation.x/ and - <tt/widget->allocation.y/. -<item> If you want the position of a window relative to the X root - window, you should use <tt/gdk_window_get_geometry()/ - <tt/gdk_window_get_position()/ or - <tt/gdk_window_get_origin()/. -<item> If you want to get the position of the window (including the WM - decorations), you should use - <tt/gdk_window_get_root_origin()/. -<item> Last but not least, if you want to get a Window Manager frame - position, you should use - <tt/gdk_window_get_deskrelative_origin()/. -</itemize> - -Your choice of Window Manager will have an effect of the results of -the above functions. You should keep this in mind when writing your -application. This is dependant upon how the Window Managers manage the -decorations that they add around windows. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I set the size of a widget/window? How do I prevent the user resizing my window? -<p> -The <tt/gtk_widget_set_uposition()/ function is used to set the -position of any widget. - -The <tt/gtk_widget_set_usize()/ function is used to set the size of a -widget. In order to use all the features that are provided by this -function when it acts on a window, you may want to use the -<tt/gtk_window_set_policy/ function. The definition of these functions -are: - -<tscreen><verb> -void gtk_widget_set_usize (GtkWidget *widget, - gint width, - gint height); - -void gtk_window_set_policy (GtkWindow *window, - gint allow_shrink, - gint allow_grow, - gint auto_shrink); -</verb></tscreen> - -<tt/Auto_shrink/ will automatically shrink the window when the -requested size of the child widgets goes below the current size of the -window. <tt/Allow_shrink/ will give the user the authorisation to make -the window smaller that it should normally be. <tt/Allow_grow/ will -give the user will have the ability to make the window bigger. The -default values for these parameters are: - -<tscreen><verb> -allow_shrink = FALSE -allow_grow = TRUE -auto_shrink = FALSE -</verb></tscreen> - -The <tt/gtk_widget_set_usize()/ functions is not the easiest way to -set a window size since you cannot decrease this window size with -another call to this function unless you call it twice, as in: - -<tscreen><verb> - gtk_widget_set_usize(your_widget, -1, -1); - gtk_widget_set_usize(your_widget, new_x_size, new_y_size); -</verb></tscreen> - -Another way to set the size of and/or move a window is to use the -<tt/gdk_window_move_resize()/ function which uses to work fine both to -grow or to shrink the window: - -<tscreen><verb> - gdk_window_move_resize(window->window, - x_pos, y_pos, - x_size, y_size); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I add a popup menu to my GTK+ application? -<p> -The <tt/menu/ example in the examples/menu directory of the GTK+ distribution -implements a popup menu with this technique : - -<tscreen><verb> -static gint button_press (GtkWidget *widget, GdkEvent *event) -{ - - if (event->type == GDK_BUTTON_PRESS) { - GdkEventButton *bevent = (GdkEventButton *) event; - gtk_menu_popup (GTK_MENU(widget), NULL, NULL, NULL, NULL, - bevent->button, bevent->time); - /* Tell calling code that we have handled this event; the buck - * stops here. */ - return TRUE; - } - - /* Tell calling code that we have not handled this event; pass it on. */ - return FALSE; -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I disable or enable a widget, such as a button? -<p> -To disable (or to enable) a widget, use the -<tt/gtk_widget_set_sensitive()/ function. The first parameter is you -widget pointer. The second parameter is a boolean value: when this -value is TRUE, the widget is enabled. - -<!-- ----------------------------------------------------------------- --> -<sect1>Shouldn't the text argument in the gtk_clist_* functions be declared const? -<p> -For example: -<verb> -gint gtk_clist_prepend (GtkCList *clist, - gchar *text[]); -</verb> - -Answer: No, while a type "gchar*" (pointer to char) can automatically -be cast into "const gchar*" (pointer to const char), this does not -apply for "gchar *[]" (array of an unspecified number of pointers to -char) into "const gchar *[]" (array of an unspecified number of -pointers to const char). - -The type qualifier "const" may be subject to automatic casting, but in -the array case, it is not the array itself that needs the (const) -qualified cast, but its members, thus changing the whole type. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I render pixels (image data) to the screen? -<p> -There are several ways to approach this. The simplest way is to use -GdkRGB, see gdk/gdkrgb.h. You create an RGB buffer, render to your RGB -buffer, then use GdkRGB routines to copy your RGB buffer to a drawing -area or custom widget. The book "GTK+/Gnome Application Development" -gives some details; GdkRGB is also documented in the GTK+ reference -documentation. - -If you're writing a game or other graphics-intensive application, you -might consider a more elaborate solution. OpenGL is the graphics -standard that will let you access hardware accelaration in future -versions of XFree86; so for maximum speed, you probably want to use -OpenGL. A GtkGLArea widget is available for using OpenGL with GTK+ -(but GtkGLArea does not come with GTK+ itself). There are also several -open source game libraries, such as ClanLib and Loki's Simple -DirectMedia Layer library (SDL). - -You do NOT want to use <tt/gdk_draw_point()/, that will be extremely -slow. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I create a pixmap without having my window realized/shown? -<p> -Functions such as <tt/gdk_pixmap_create_from_xpm()/ require a valid -window as a parameter. During the initialisation phase of an -application, a valid window may not be available without showing a -window, which may be inappropriate. In order to avoid this, a -function such as <tt/gdk_pixmap_colormap_create_from_xpm/ can be used, -as in: - -<tscreen><verb> - char *pixfile = "foo.xpm"; - GtkWidget *top, *box, *pixw; - GdkPixmap *pixmap, *pixmap_mask; - - top = gtk_window_new (GKT_WINDOW_TOPLEVEL); - box = gtk_hbox_new (FALSE, 4); - gtk_conainer_add (GTK_CONTAINER(top), box); - - pixmap = gdk_pixmap_colormap_create_from_xpm ( - NULL, gtk_widget_get_colormap(top), - &pixmap_mask, NULL, pixfile); - pixw = gtk_pixmap_new (pixmap, pixmap_mask); - gdk_pixmap_unref (pixmap); - gdk_pixmap_unref (pixmap_mask); - -</verb></tscreen> - -<!-- ***************************************************************** --> -<sect>Development with GTK+: widget specific questions -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I find out about the selection of a GtkList? -<p> -Get the selection something like this: -<tscreen><verb> -GList *sel; -sel = GTK_LIST(list)->selection; -</verb></tscreen> - -This is how GList is defined (quoting glist.h): -<tscreen><verb> -typedef struct _GList GList; - -struct _GList -{ - gpointer data; - GList *next; - GList *prev; -}; -</verb></tscreen> - -A GList structure is just a simple structure for doubly linked lists. -there exist several g_list_*() functions to modify a linked list in -glib.h. However the GTK_LIST(MyGtkList)->selection is maintained -by the gtk_list_*() functions and should not be modified. - -The selection_mode of the GtkList determines the selection -facilities of a GtkList and therefore the contents -of GTK_LIST(AnyGtkList)->selection: - -<verb> -selection_mode GTK_LIST()->selection contents ------------------------------------------------------- - -GTK_SELECTION_SINGLE selection is either NULL - or contains a GList* pointer - for a single selected item. - -GTK_SELECTION_BROWSE selection is NULL if the list - contains no widgets, otherwise - it contains a GList* pointer - for one GList structure. - -GTK_SELECTION_MULTIPLE selection is NULL if no listitems - are selected or a a GList* pointer - for the first selected item. that - in turn points to a GList structure - for the second selected item and so - on. - -GTK_SELECTION_EXTENDED selection is NULL. -</verb> - -The data field of the GList structure GTK_LIST(MyGtkList)->selection points -to the first GtkListItem that is selected. So if you would like to determine -which listitems are selected you should go like this: - -Upon Initialization: -<tscreen><verb> -{ - gchar *list_items[]={ - "Item0", - "Item1", - "foo", - "last Item", - }; - guint nlist_items=sizeof(list_items)/sizeof(list_items[0]); - GtkWidget *list_item; - guint i; - - list=gtk_list_new(); - gtk_list_set_selection_mode(GTK_LIST(list), GTK_SELECTION_MULTIPLE); - gtk_container_add(GTK_CONTAINER(AnyGtkContainer), list); - gtk_widget_show (list); - - for (i = 0; i < nlist_items; i++) - { - list_item=gtk_list_item_new_with_label(list_items[i]); - gtk_object_set_user_data(GTK_OBJECT(list_item), (gpointer)i); - gtk_container_add(GTK_CONTAINER(list), list_item); - gtk_widget_show(list_item); - } -} -</verb></tscreen> - -To get known about the selection: -<tscreen><verb> -{ - GList *items; - - items=GTK_LIST(list)->selection; - - printf("Selected Items: "); - while (items) { - if (GTK_IS_LIST_ITEM(items->data)) - printf("%d ", (guint) - gtk_object_get_user_data(items->data)); - items=items->next; - } - printf("\n"); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I stop the column headings of a GtkCList disappearing -when the list is scrolled? -<p> -This happens when a GtkCList is packed into a GtkScrolledWindow using -the function <tt/gtk_scroll_window_add_with_viewport()/. The prefered -method of adding a CList to a scrolled window is to use the function -<tt/gtk_container_add/, as in: - -<tscreen><verb> - GtkWidget *scrolled, *clist; - char *titles[] = { "Title1" , "Title2" }; - - scrolled = gtk_scrolled_window_new(NULL, NULL); - - clist = gtk_clist_new_with_titles(2, titles); - gtk_container_add(GTK_CONTAINER(scrolled), clist); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --><p> -<sect1>I don't want the user of my applications to enter text into a GtkCombo. Any idea? -<p> -A GtkCombo has an associated entry which can be accessed using the -following expression: - -<tscreen><verb> - GTK_COMBO(combo_widget)->entry -</verb></tscreen> - -If you don't want the user to be able to modify the content of this -entry, you can use the gtk_entry_set_editable() function: - -<tscreen><verb> - void gtk_entry_set_editable(GtkEntry *entry, - gboolean editable); -</verb></tscreen> - -Set the editable parameter to FALSE to disable typing into the entry. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I catch a combo box change? -<p> -The entry which is associated to your GtkCombo send a "changed" signal -when: -<itemize> - <item>some text is typed in - <item>the selection of the combo box is changed -</itemize> - -To catch any combo box change, simply connect your signal handler with - -<tscreen><verb> - gtk_signal_connect(GTK_COMBO(cb)->entry, - "changed", - GTK_SIGNAL_FUNC(my_cb_change_handler), - NULL); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How can I define a separation line in a menu? -<p> -See the <htmlurl url="http://www.gtk.org/tutorial/" -name="Tutorial"> for information on how to create menus. -However, to create a separation line in a menu, just insert an -empty menu item: - -<tscreen><verb> -menuitem = gtk_menu_item_new(); -gtk_menu_append(GTK_MENU(menu), menuitem); -gtk_widget_show(menuitem); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How can I right justify a menu, such as Help? -<p> -Depending on if you use the MenuFactory or not, there are two ways to -proceed. With the MenuFactory, use something like the following: - -<tscreen><verb> -menu_path = gtk_menu_factory_find (factory, "<MyApp>/Help"); -gtk_menu_item_right_justify(menu_path->widget); -</verb></tscreen> - -If you do not use the MenuFactory, you should simply use: - -<tscreen><verb> -gtk_menu_item_right_justify(my_menu_item); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I add some underlined accelerators to menu items? -<p> -Damon Chaplin, the technical force behind the Glade project, provided -the following code sample (this code is an output from Glade). It -creates a small <tt/File/ menu item with only one child -(<tt/New/). The F in <tt/File/ and the N in <tt/New/ are underlined, -and the relevant accelerators are created. - -<tscreen><verb> - menubar1 = gtk_menu_bar_new (); - gtk_object_set_data (GTK_OBJECT (window1), "menubar1", menubar1); - gtk_widget_show (menubar1); - gtk_box_pack_start (GTK_BOX (vbox1), menubar1, FALSE, FALSE, 0); - - file1 = gtk_menu_item_new_with_label (""); - tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (file1)->child), - _("_File")); - gtk_widget_add_accelerator (file1, "activate_item", accel_group, - tmp_key, GDK_MOD1_MASK, 0); - gtk_object_set_data (GTK_OBJECT (window1), "file1", file1); - gtk_widget_show (file1); - gtk_container_add (GTK_CONTAINER (menubar1), file1); - - file1_menu = gtk_menu_new (); - file1_menu_accels = gtk_menu_ensure_uline_accel_group (GTK_MENU (file1_menu)); - gtk_object_set_data (GTK_OBJECT (window1), "file1_menu", file1_menu); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (file1), file1_menu); - - new1 = gtk_menu_item_new_with_label (""); - tmp_key = gtk_label_parse_uline (GTK_LABEL (GTK_BIN (new1)->child), - _("_New")); - gtk_widget_add_accelerator (new1, "activate_item", file1_menu_accels, - tmp_key, 0, 0); - gtk_object_set_data (GTK_OBJECT (window1), "new1", new1); - gtk_widget_show (new1); - gtk_container_add (GTK_CONTAINER (file1_menu), new1); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How can I retrieve the text from a GtkMenuItem? -<p> -You can usually retrieve the label of a specific GtkMenuItem with: - -<tscreen><verb> - if (GTK_BIN (menu_item)->child) - { - GtkWidget *child = GTK_BIN (menu_item)->child; - - /* do stuff with child */ - if (GTK_IS_LABEL (child)) - { - gchar *text; - - gtk_label_get (GTK_LABEL (child), &text); - g_print ("menu item text: %s\n", text); - } - } -</verb></tscreen> - -To get the active menu item from a GtkOptionMenu you can do: -<tscreen><verb> -if (GTK_OPTION_MENU (option_menu)->menu_item) -{ - GtkWidget *menu_item = GTK_OPTION_MENU (option_menu)->menu_item; -} -</verb></tscreen> - -But, there's a catch. For this specific case, you can <bf>not</bf> get -the label widget from <tt/menu_item/ with the above code, because the -option menu reparents the menu_item's child temporarily to display the -currently active contents. So to retrive the child of the currently -active menu_item of an option menu, you'll have to do: - -<tscreen><verb> - if (GTK_BIN (option_menu)->child) - { - GtkWidget *child = GTK_BIN (option_menu)->child; - - /* do stuff with child */ - } -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I right (or otherwise) justify a GtkLabel? -<p> -Are you sure you want to <em>justify</em> the labels? The label class -contains the <tt/gtk_label_set_justify()/ function that is used to -control the justification of a multi-line label. - -What you probably want is to set the <em>alignment</em> of the label, -ie right align it, center it or left align it. If you want to do this, -you should use: - -<tscreen><verb> -void gtk_misc_set_alignment (GtkMisc *misc, - gfloat xalign, - gfloat yalign); -</verb></tscreen> - -where the <tt/xalign/ and <tt/yalign/ values are floats in [0.00;1.00]. - -<tscreen><verb> -GtkWidget *label; - -/* horizontal : left align, vertical : top */ -gtk_misc_set_alignment(GTK_MISK(label), 0.0f, 0.0f); - -/* horizontal : centered, vertical : centered */ -gtk_misc_set_alignment(GTK_MISK(label), 0.5f, 0.5f); - -/* horizontal : right align, vertical : bottom */ -gtk_misc_set_alignment(GTK_MISK(label), 1.0f, 1.0f); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I set the background color of a GtkLabel widget? -<p> -The Gtklabel widget is one of a few GTK+ widgets that don't create -their own window to render themselves into. Instead, they draw -themselves directly onto their parents window. - -This means that in order to set the background color for a GtkLabel -widget, you need to change the background color of its parent, -i.e. the object that you pack it into. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I set the color and font of a GtkLabel using a Resource File? -<p> -The widget name path constructed for a Label consists of the widget -names of its object hierarchy as well, e.g. - -<verb> -window (name: humphrey) - hbox - label (name: mylabel) -</verb> - -The widget path your pattern needs to match would be: -<tt/humphrey.GtkHBox.mylabel/ - -The resource file may look something like: - -<verb> -style "title" -{ - fg[NORMAL] = {1.0, 0.0, 0.0} - font = "-adobe-helvetica-bold-r-normal--*-140-*-*-*-*-*-*" -} -widget "*mylabel" style "title" -</verb> - -In your program, you would also need to give a name to the Label -widget, which can be done using: -<verb> - label = gtk_label_new("Some Label Text"); - gtk_widget_set_name(label, "mylabel"); - gtk_widget_show(label); -</verb> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I configure Tooltips in a Resource File? -<p> -The tooltip's window is named "gtk-tooltips", GtkTooltips in itself is -not a GtkWidget (though a GtkObject) and as such is not attempted to -match any widget styles. - -So, you resource file should look something like: -<verb> -style "postie" -{ - bg[NORMAL] = {1.0, 1.0, 0.0} -} -widget "gtk-tooltips*" style "postie" -</verb> - -<!-- ----------------------------------------------------------------- --> -<sect1>I can't add more than (something like) 2000 chars in a GtkEntry. What's wrong? -<p> -There is now a known problem in the GtkEntry widget. In the -<tt/gtk_entry_insert_text()/ function, the following lines limit -the number of chars in the entry to 2047. - -<tscreen><verb> - /* The algorithms here will work as long as, the text size (a - * multiple of 2), fits into a guint16 but we specify a shorter - * maximum length so that if the user pastes a very long text, there - * is not a long hang from the slow X_LOCALE functions. */ - - if (entry->text_max_length == 0) - max_length = 2047; - else - max_length = MIN (2047, entry->text_max_length); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I make a GtkEntry widget activate on pressing the Return key? -<p> -The Entry widget emits an 'activate' signal when you press return in -it. Just attach to the activate signal on the entry and do whatever you -want to do. Typical code would be: - -<tscreen><verb> - entry = gtk_entry_new(); - gtk_signal_connect (GTK_OBJECT(entry), "activate", - GTK_SIGNAL_FUNC(entry_callback), - NULL); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I validate/limit/filter the input to a GtkEntry? -<p> -If you want to validate the text that a user enters into a GtkEntry -widget you can attach to the "insert_text" signal of the entry, and -modify the text within the callback function. The example below forces -all characters to uppercase, and limits the range of characters to -A-Z. Note that the entry is cast to an object of type GtkEditable, -from which GtkEntry is derived. - -<tscreen><verb> -#include <ctype.h> -#include <gtk/gtk.h> - -void insert_text_handler (GtkEntry *entry, - const gchar *text, - gint length, - gint *position, - gpointer data) -{ - GtkEditable *editable = GTK_EDITABLE(entry); - int i, count=0; - gchar *result = g_new (gchar, length); - - for (i=0; i < length; i++) { - if (!isalpha(text[i])) - continue; - result[count++] = islower(text[i]) ? toupper(text[i]) : text[i]; - } - - if (count > 0) { - gtk_signal_handler_block_by_func (GTK_OBJECT (editable), - GTK_SIGNAL_FUNC (insert_text_handler), - data); - gtk_editable_insert_text (editable, result, count, position); - gtk_signal_handler_unblock_by_func (GTK_OBJECT (editable), - GTK_SIGNAL_FUNC (insert_text_handler), - data); - } - gtk_signal_emit_stop_by_name (GTK_OBJECT (editable), "insert_text"); - - g_free (result); -} - -int main (int argc, - char *argv[]) -{ - GtkWidget *window; - GtkWidget *entry; - - gtk_init (&argc, &argv); - - /* create a new window */ - window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW (window), "GTK Entry"); - gtk_signal_connect(GTK_OBJECT (window), "delete_event", - (GtkSignalFunc) gtk_exit, NULL); - - entry = gtk_entry_new(); - gtk_signal_connect(GTK_OBJECT(entry), "insert_text", - GTK_SIGNAL_FUNC(insert_text_handler), - NULL); - gtk_container_add(GTK_CONTAINER (window), entry); - gtk_widget_show(entry); - - gtk_widget_show(window); - - gtk_main(); - return(0); -} -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I use horizontal scrollbars with a GtkText widget? -<p> -The short answer is that you can't. The current version of the GtkText -widget does not support horizontal scrolling. There is an intention to -completely rewrite the GtkText widget, at which time this limitation -will be removed. - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I change the font of a GtkText widget? -<p> -There are a couple of ways of doing this. As GTK+ allows the -appearance of applications to be changed at run time using resources -you can use something like the following in the appropriate -file: - -<tscreen><verb> -style "text" -{ - font = "-adobe-helvetica-medium-r-normal--*-100-*-*-*-*-*-*" -} -</verb></tscreen> - -Another way to do this is to load a font within your program, and then -use this in the functions for adding text to the text widget. You can -load a font using, for example: - -<tscreen><verb> - GdkFont *font; - font = gdk_font_load("-adobe-helvetica-medium-r-normal--*-140-*-*-*-*-*-*"); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I set the cursor position in a GtkText object? -<p> -Notice that the response is valid for any object that inherits from the -GtkEditable class. - -Are you sure that you want to move the cursor position? Most of the -time, while the cursor position is good, the insertion point does not -match the cursor position. If this apply to what you really want, then -you should use the <tt/gtk_text_set_point()/ function. If you want to -set the insertion point at the current cursor position, use the -following: - -<tscreen><verb> - gtk_text_set_point(GTK_TEXT(text), - gtk_editable_get_position(GTK_EDITABLE(text))); -</verb></tscreen> - -If you want the insertion point to follow the cursor at all time, you -should probably catch the button press event, and then move the -insertion point. Be careful : you'll have to catch it after the widget -has changed the cursor position though. Thomas Mailund Jensen proposed -the following code: - -<tscreen><verb> -static void -insert_bar (GtkWidget *text) -{ - /* jump to cursor mark */ - gtk_text_set_point (GTK_TEXT (text), - gtk_editable_get_position (GTK_EDITABLE (text))); - - gtk_text_insert (GTK_TEXT (text), NULL, NULL, NULL, - "bar", strlen ("bar")); -} - -int -main (int argc, char *argv[]) -{ - GtkWidget *window, *text; - - gtk_init (&argc, &argv); - - window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - text = gtk_text_new (NULL, NULL); - gtk_text_set_editable (GTK_TEXT (text), TRUE); - gtk_container_add (GTK_CONTAINER (window), text); - - /* connect after everything else */ - gtk_signal_connect_after (GTK_OBJECT(text), "button_press_event", - GTK_SIGNAL_FUNC (insert_bar), NULL); - - gtk_widget_show_all(window); - gtk_main(); - - return 0; -} -</verb></tscreen> - -Now, if you really want to change the cursor position, you should use the -<tt/gtk_editable_set_position()/ function. - -<!-- ***************************************************************** --> -<sect>About gdk -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>What is GDK? -<p> -GDK is basically a wrapper around the standard Xlib function calls. If -you are at all familiar with Xlib, a lot of the functions in GDK will -require little or no getting used to. All functions are written to -provide an way to access Xlib functions in an easier and slightly more -intuitive manner. In addition, since GDK uses GLib (see below), it -will be more portable and safer to use on multiple platforms. - -<!-- Examples, anybody? I've been mulling some over. NF --> - -<!-- ----------------------------------------------------------------- --> -<sect1>How do I use color allocation? -<p> -One of the nice things about GDK is that it's based on top of Xlib; this is -also a problem, especially in the area of color management. If you want -to use color in your program (drawing a rectangle or such, your code -should look something like this: -<tscreen> -<verb> -{ - GdkColor *color; - int width, height; - GtkWidget *widget; - GdkGC *gc; - - ... - - /* first, create a GC to draw on */ - gc = gdk_gc_new(widget->window); - - /* find proper dimensions for rectangle */ - gdk_window_get_size(widget->window, &width, &height); - - /* the color we want to use */ - color = (GdkColor *)malloc(sizeof(GdkColor)); - - /* red, green, and blue are passed values, indicating the RGB triple - * of the color we want to draw. Note that the values of the RGB components - * within the GdkColor are taken from 0 to 65535, not 0 to 255. - */ - color->red = red * (65535/255); - color->green = green * (65535/255); - color->blue = blue * (65535/255); - - /* the pixel value indicates the index in the colormap of the color. - * it is simply a combination of the RGB values we set earlier - */ - color->pixel = (gulong)(red*65536 + green*256 + blue); - - /* However, the pixel valule is only truly valid on 24-bit (TrueColor) - * displays. Therefore, this call is required so that GDK and X can - * give us the closest color available in the colormap - */ - gdk_color_alloc(gtk_widget_get_colormap(widget), color); - - /* set the foreground to our color */ - gdk_gc_set_foreground(gc, color); - - /* draw the rectangle */ - gdk_draw_rectangle(widget->window, gc, 1, 0, 0, width, height); - - ... -} -</verb> -</tscreen> - -<!-- ***************************************************************** --> -<sect>About GLib -<!-- ***************************************************************** --> - -<!-- ----------------------------------------------------------------- --> -<sect1>What is GLib? -<p> -GLib is a library of useful functions and definitions available for use -when creating GDK and GTK applications. It provides replacements for some -standard libc functions, such as malloc, which are buggy on some systems. -<p> -It also provides routines for handling: -<itemize> -<item>Doubly Linked Lists -<item>Singly Linked Lists -<item>Timers -<item>String Handling -<item>A Lexical Scanner -<item>Error Functions -</itemize> - -<!-- ----------------------------------------------------------------- --> -<sect1>How can I use the doubly linked lists? -<p> -The GList object is defined as: - -<tscreen><verb> -typedef struct _GList GList; - -struct _GList -{ - gpointer data; - GList *next; - GList *prev; -}; -</verb></tscreen> - -To use the GList objects, simply : - -<tscreen><verb> -GList *list = NULL; -GList *listrunner; -gint array[] = { 1, 2, 3, 4, 5, 6 }; -gint pos; -gint *value; - -/* add data to the list */ -for (pos=0;pos < sizeof array; pos++) { - list = g_list_append(list, (gpointer)&array[pos]); -} - -/* run through the list */ -listrunner = g_list_first(list); -while (listrunner) { - value = (gint *)listrunner->data; - printf("%d\n", *value); - listrunner = g_list_next(listrunner); -} - -/* removing datas from the list */ -listrunner = g_list_first(list); -list = g_list_remove_link(list, listrunner); -list = g_list_remove(list, &array[4]); -</verb></tscreen> - -The same code is usable with singly linked lists (GSList objects) by replacing -g_list_* functions with the relevant g_slist_* ones (g_slist_append, -g_slist_remove, ...). Just remember that since you can't go backward in a singly -linked list, there is no g_slist_first function - you'll need to keep a -reference on the first node of the list. - -<!-- Some Examples might be useful here! NF --> -<!-- I believe it should be better :) ED --> -<!-- Linked lists are pretty standard data structures - don't want to - over do it - TRG --> - -<!-- ----------------------------------------------------------------- --> -<sect1>Memory does not seem to be released when I free the list nodes I've allocated -<p> -GLib tries to be "intelligent" on this special issue: it assumes that -you are likely to reuse the objects, so caches the allocated memory. -If you do not want to use this behavior, you'll probably want to set -up a special allocator. - -To quote Tim Janik: -<quote> -If you have a certain portion of code that uses *lots* of GLists or -GNodes, and you know you'd better want to release all of them after a -short while, you'd want to use a GAllocator. Pushing an allocator into -g_list will make all subsequent glist operations private to that -allocator's memory pool (and thus you have to take care to pop the -allocator again, before making any external calls): -</quote> - -<tscreen><verb> -GAllocator *allocator; -GList *list = NULL; -guint i; - -/* set a new allocation pool for GList nodes */ -allocator = g_allocator_new ("list heap", 1024); -g_list_push_allocator (allocator); - -/* do some list operations */ -for (i = 0; i < 4096; i++) - list = g_list_prepend (list, NULL); -list = g_list_reverse (list); - -/* beware to pop allocator befor calling external functions */ -g_list_pop_allocator (); -gtk_label_set_text (GTK_LABEL (some_label), "some text"); - -/* and set our private glist pool again */ -g_list_push_allocator (allocator); - -/* do some list operations */ -g_list_free (list); -list = NULL; -for (i = 0; i < 4096; i++) - list = g_list_prepend (list, NULL); - -/* and back out (while freeing all of the list nodes in our pool) */ -g_list_pop_allocator (); -g_allocator_free (allocator); -</verb></tscreen> - -<!-- ----------------------------------------------------------------- --> -<sect1>Why use g_print, g_malloc, g_strdup and fellow glib functions? -<p> -Thanks to Tim Janik who wrote to gtk-list: (slightly modified) -<quote> -Regarding g_malloc(), g_free() and siblings, these functions are much -safer than their libc equivalents. For example, g_free() just returns -if called with NULL. Also, if USE_DMALLOC is defined, the definition -for these functions changes (in glib.h) to use MALLOC(), FREE() etc... -If MEM_PROFILE or MEM_CHECK are defined, there are even small -statistics made counting the used block sizes (shown by -g_mem_profile() / g_mem_check()). -<p> -Considering the fact that glib provides an interface for memory chunks -to save space if you have lots of blocks that are always the same size -and to mark them ALLOC_ONLY if needed, it is just straight forward to -create a small saver (debug able) wrapper around the normal malloc/free -stuff as well - just like gdk covers Xlib. ;) -<p> -Using g_error() and g_warning() inside of applications like the GIMP -that fully rely on gtk even gives the opportunity to pop up a window -showing the messages inside of a gtk window with your own handler -(by using g_set_error_handler()) along the lines of <tt/gtk_print()/ -(inside of gtkmain.c). -</quote> - -<!-- ----------------------------------------------------------------- --> -<sect1>What's a GScanner and how do I use one? -<p> -A GScanner will tokenize your text, that is, it'll return an integer -for every word or number that appears in its input stream, following -certain (customizable) rules to perform this translation. -You still need to write the parsing functions on your own though. - -Here's a little test program supplied by Tim Janik that will parse - -<verb> -<SYMBOL> = <OPTIONAL-MINUS> <NUMBER> ; -</verb> - -constructs, while skipping "#\n" and "/**/" style comments. - -<verb> -#include <glib.h> - -/* some test text to be fed into the scanner */ -static const gchar *test_text = -( "ping = 5;\n" - "/* slide in some \n" - " * comments, just for the\n" - " * fun of it \n" - " */\n" - "pong = -6; \n" - "\n" - "# the next value is a float\n" - "zonk = 0.7;\n" - "# redefine ping\n" - "ping = - 0.5;\n" ); - -/* define enumeration values to be returned for specific symbols */ -enum { - SYMBOL_PING = G_TOKEN_LAST + 1, - SYMBOL_PONG = G_TOKEN_LAST + 2, - SYMBOL_ZONK = G_TOKEN_LAST + 3 -}; - -/* symbol array */ -static const struct { - gchar *symbol_name; - guint symbol_token; -} symbols[] = { - { "ping", SYMBOL_PING, }, - { "pong", SYMBOL_PONG, }, - { "zonk", SYMBOL_ZONK, }, - { NULL, 0, }, -}, *symbol_p = symbols; - -static gfloat ping = 0; -static gfloat pong = 0; -static gfloat zonk = 0; - -static guint -parse_symbol (GScanner *scanner) -{ - guint symbol; - gboolean negate = FALSE; - - /* expect a valid symbol */ - g_scanner_get_next_token (scanner); - symbol = scanner->token; - if (symbol < SYMBOL_PING || - symbol > SYMBOL_ZONK) - return G_TOKEN_SYMBOL; - - /* expect '=' */ - g_scanner_get_next_token (scanner); - if (scanner->token != '=') - return '='; - - /* feature optional '-' */ - g_scanner_peek_next_token (scanner); - if (scanner->next_token == '-') - { - g_scanner_get_next_token (scanner); - negate = !negate; - } - - /* expect a float (ints are converted to floats on the fly) */ - g_scanner_get_next_token (scanner); - if (scanner->token != G_TOKEN_FLOAT) - return G_TOKEN_FLOAT; - - /* make sure the next token is a ';' */ - if (g_scanner_peek_next_token (scanner) != ';') - { - /* not so, eat up the non-semicolon and error out */ - g_scanner_get_next_token (scanner); - return ';'; - } - - /* assign value, eat the semicolon and exit successfully */ - switch (symbol) - { - case SYMBOL_PING: - ping = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - case SYMBOL_PONG: - pong = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - case SYMBOL_ZONK: - zonk = negate ? - scanner->value.v_float : scanner->value.v_float; - break; - } - g_scanner_get_next_token (scanner); - - return G_TOKEN_NONE; -} - -int -main (int argc, char *argv[]) -{ - GScanner *scanner; - guint expected_token; - - scanner = g_scanner_new (NULL); - - /* adjust lexing behaviour to suit our needs - */ - /* convert non-floats (octal values, hex values...) to G_TOKEN_INT */ - scanner->config->numbers_2_int = TRUE; - /* convert G_TOKEN_INT to G_TOKEN_FLOAT */ - scanner->config->int_2_float = TRUE; - /* don't return G_TOKEN_SYMBOL, but the symbol's value */ - scanner->config->symbol_2_token = TRUE; - - /* load symbols into the scanner */ - while (symbol_p->symbol_name) - { - g_scanner_add_symbol (scanner, - symbol_p->symbol_name, - GINT_TO_POINTER (symbol_p->symbol_token)); - symbol_p++; - } - - /* feed in the text */ - g_scanner_input_text (scanner, test_text, strlen (test_text)); - - /* give the error handler an idea on how the input is named */ - scanner->input_name = "test text"; - - /* scanning loop, we parse the input until its end is reached, - * the scanner encountered a lexing error, or our sub routine came - * across invalid syntax - */ - do - { - expected_token = parse_symbol (scanner); - - g_scanner_peek_next_token (scanner); - } - while (expected_token == G_TOKEN_NONE && - scanner->next_token != G_TOKEN_EOF && - scanner->next_token != G_TOKEN_ERROR); - - /* give an error message upon syntax errors */ - if (expected_token != G_TOKEN_NONE) - g_scanner_unexp_token (scanner, expected_token, NULL, "symbol", NULL, NULL, TRUE); - - /* finsish parsing */ - g_scanner_destroy (scanner); - - /* print results */ - g_print ("ping: %f\n", ping); - g_print ("pong: %f\n", pong); - g_print ("zonk: %f\n", zonk); - - return 0; -} -</verb> - -You need to understand that the scanner will parse its input and -tokenize it, it is up to you to interpret these tokens, not define -their types before they get parsed, e.g. watch gscanner parse a -string: - -<verb> -"hi i am 17" - | | | | - | | | v - | | v TOKEN_INT, value: 17 - | v TOKEN_IDENTIFIER, value: "am" - v TOKEN_CHAR, value: 'i' -TOKEN_IDENTIFIER, value: "hi" -</verb> - -If you configure the scanner with: -<verb> -scanner->config->int_2_float = TRUE; -scanner->config->char_2_token = TRUE; -scanner->config->scan_symbols = TRUE; -</verb> - -and add "am" as a symbol with -<verb> -g_scanner_add_symbol (scanner, "am", "symbol value"); -</verb> - -GScanner will parse it as - -<verb> -"hi i am 17" - | | | | - | | | v - | | v TOKEN_FLOAT, value: 17.0 (automatic int->float conversion) - | | TOKEN_SYMBOL, value: "symbol value" (a successfull hash table lookup - | | turned a TOKEN_IDENTIFIER into a - | | TOKEN_SYMBOL and took over the - | v symbol's value) - v 'i' ('i' can be a valid token as well, as all chars >0 and <256) -TOKEN_IDENTIFIER, value: "hi" -</verb> - -You need to match the token sequence with your code, and if you encounter -something that you don't want, you error out: - -<verb> -/* expect an identifier ("hi") */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_IDENTIFIER) - return G_TOKEN_IDENTIFIER; -/* expect a token 'i' */ -g_scanner_get_next_token (scanner); -if (scanner->token != 'i') - return 'i'; -/* expect a symbol ("am") */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_SYMBOL) - return G_TOKEN_SYMBOL; -/* expect a float (17.0) */ -g_scanner_get_next_token (scanner); -if (scanner->token != G_TOKEN_FLOAT) - return G_TOKEN_FLOAT; -</verb> - -If you got past here, you have parsed "hi i am 17" and would have -accepted "dooh i am 42" and "bah i am 0.75" as well, but you would -have not accepted "hi 7 am 17" or "hi i hi 17". - -<!-- ***************************************************************** --> -<sect>GTK+ FAQ Contributions, Maintainers and Copyright -<p> -If you would like to make a contribution to the FAQ, send either one -of us an e-mail message with the exact text you think should be -included (question and answer). With your help, this document can grow -and become more useful! - -This document is maintained by -Tony Gale <htmlurl url="mailto:gale@gtk.org" -name="<gale@gtk.org>"> -Nathan Froyd <htmlurl url="mailto:maestrox@geocities.com" -name="<maestrox@geocities.com>">, -and -Emmanuel Deloget <htmlurl url="mailto:logout@free.fr" -name="<logout@free.fr>">. -This FAQ was created by Shawn T. Amundson -<htmlurl url="mailto:amundson@gimp.org" -name="<amundson@gimp.org>"> who continues to provide support. - -Contributions should be sent to Tony Gale <htmlurl -url="mailto:gale@gtk.org" name="<gale@gtk.org>"> - -The GTK+ FAQ is Copyright (C) 1997-2000 by Shawn T. Amundson, -Tony Gale, Emmanuel Deloget and Nathan Froyd. - -Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - -Permission is granted to copy and distribute modified versions of this -document under the conditions for verbatim copying, provided that this -copyright notice is included exactly as in the original, and that the -entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - -Permission is granted to copy and distribute translations of this -document into another language, under the above conditions for -modified versions. - -If you are intending to incorporate this document into a published -work, please contact one of the maintainers, and we will make an -effort to ensure that you have the most up to date information -available. - -There is no guarentee that this document lives up to its intended -purpose. This is simply provided as a free resource. As such, the -authors and maintainers of the information provided within can not -make any guarentee that the information is even accurate. - -</article> -- 2.30.2